package heap

import (
	"fmt"
	"jvm/nzpJvm/classfile"
)

// 表示运行时常量池中一个常量的接口
// 可以存储任何类型
type Constant interface {
}

// 一个heap.ConstantPool结构体代表一个运行时常量池
type ConstantPool struct {
	class  *Class
	consts []Constant
}

// 根据class文件中解析出来的常量池，创建一个新的运行时常量池
func newConstantPool(class *Class, cfCp classfile.ConstantPool) *ConstantPool {
	cpCount := len(cfCp)
	// 运行时常量池
	consts := make([]Constant, cpCount)
	constantPool := &ConstantPool{}
	constantPool.consts = consts
	constantPool.class = class
	for i := 0; i < cpCount; i++{
		cpInfo := cfCp[i]
		switch cpInfo.(type) {
		case *classfile.ConstantIntegerInfo:
			info := cpInfo.(*classfile.ConstantIntegerInfo)
			consts[i] = info.Value()
		case *classfile.ConstantFloatInfo:
			info := cpInfo.(*classfile.ConstantFloatInfo)
			consts[i] = info.Value()
		case *classfile.ConstantLongInfo:
			info := cpInfo.(*classfile.ConstantLongInfo)
			consts[i] = info.Value()
			// long类型占两个位置
			i++
		case *classfile.ConstantDoubleInfo:
			info := cpInfo.(*classfile.ConstantDoubleInfo)
			consts[i] = info.Value()
			// double类型占两个位置
			i++
		case *classfile.ConstantStringInfo:
			info := cpInfo.(*classfile.ConstantStringInfo)
			consts[i] = info.String()
		case *classfile.ConstantClassInfo:
			info := cpInfo.(*classfile.ConstantClassInfo)
			consts[i] = newClassRef(constantPool,info)
		case *classfile.ConstantFieldrefInfo:
			info := cpInfo.(*classfile.ConstantFieldrefInfo)
			consts[i] =newFieldRef(constantPool,info)
		case *classfile.ConstantMethodrefInfo:
			info := cpInfo.(*classfile.ConstantMethodrefInfo)
			consts[i] =newMethodRef(constantPool,info)
		case *classfile.ConstantInterfaceMethodrefInfo:
			info := cpInfo.(*classfile.ConstantInterfaceMethodrefInfo)
			consts[i] =newInterfaceMethodRef(constantPool,info)
		}


	}
	return constantPool
}


func (self *ConstantPool) GetConstant(index uint) Constant {
	constant := self.consts[index]
	if constant == nil {
		panic(fmt.Sprintf("No constants at index %d", index))
	}
	return constant
}
